package com.jianyun.jyzs.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.ImageView;


import com.jianyun.jyzs.R;
import com.jianyun.jyzs.ThisApp;
import com.jianyun.jyzs.utils.BitmapUtils;
import com.jianyun.jyzs.utils.DateTime;
import com.jrmf360.rylib.common.util.ScreenUtil;

import java.util.ArrayList;
import java.util.List;

@SuppressLint("AppCompatCustomView")
public class MosaicView extends ImageView {
    public static final String TAG = "MosaicView";

    public static enum Effect {
        GRID, COLOR, BLUR,
    }

    ;

    // default image inner padding, in dip pixels
    private static final int INNER_PADDING = 0;

    // default grid width, in dip pixels
    private static final int GRID_WIDTH = 1;

    // default grid width, in dip pixels
    private static final int PATH_WIDTH = 5;

    // default stroke rectangle color
    private static final int STROKE_COLOR = Color.RED;

    // default stroke width, in pixels
    private static final int STROKE_WIDTH = 2;

    private int mImageWidth;
    private int mImageHeight;

    private int bottomHeight;

    private Bitmap bmBaseLayer;
    private Bitmap bmCoverLayer;
    private Bitmap bmMosaicLayer;
    private Bitmap bmTextLayer;

    private int mGridWidth;
    public int mPathWidth;

    public String text = "";

    private int mStrokeWidth;

    private int mStrokeColor;

    private Effect mEffect;

    private Rect mImageRect;

    private Paint mPaint;

    private Rect mTouchRect;
    private List<Rect> mTouchRects;

    private Path mTouchPath;
    private List<Rect> mEraseRects;

    private int mMosaicColor;
    private int mPadding;

    private List<Path> mTouchPaths;
    private List<Path> mErasePaths;

    private boolean mMosaic;

    private int textx = 20, texty = 40;
    private boolean isText = false;       //是否处理文字  


    private List<Integer> isErase = new ArrayList<Integer>();//记录每次画和擦

    public MosaicView(Context context) {
        super(context);
        initImage();
    }

    public MosaicView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initImage();
    }

    private void initImage() {
        mMosaic = true;

        mTouchRects = new ArrayList<Rect>();
        mEraseRects = new ArrayList<Rect>();

        mTouchPaths = new ArrayList<Path>();
        mErasePaths = new ArrayList<Path>();

        mStrokeWidth = STROKE_WIDTH;
        mStrokeColor = STROKE_COLOR;

        mPadding = dp2px(INNER_PADDING);

        mPathWidth = dp2px(PATH_WIDTH);
        mGridWidth = dp2px(GRID_WIDTH);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(mStrokeColor);

        mImageRect = new Rect();

        setWillNotDraw(false);

        mEffect = Effect.GRID;
    }

    public void setSrcPath(Bitmap bp) {
        if (bp == null) {
            Log.w(TAG, "Bitmap is null");
            return;
        }

        reset();

        mImageWidth = bp.getWidth();
        mImageHeight = bp.getHeight();

        bmBaseLayer = bp;

        bmCoverLayer = getCoverLayer();
        bmMosaicLayer = null;

        requestLayout();
        invalidate();
    }

    public void setEffect(Effect effect) {
        if (mEffect == effect) {
            Log.d(TAG, "duplicated effect " + effect);
            return;
        }

        this.mEffect = effect;
        if (bmCoverLayer != null) {
            bmCoverLayer.recycle();
        }

        bmCoverLayer = getCoverLayer();
        updatePathMosaic();
        invalidate();
    }

    private Bitmap getCoverLayer() {
        Bitmap bitmap = null;
        if (mEffect == Effect.GRID) {
            bitmap = getGridMosaic();
        } else if (mEffect == Effect.COLOR) {
            bitmap = getColorMosaic();
        } else if (mEffect == Effect.BLUR) {
            bitmap = getBlurMosaic();
        }
        return bitmap;
    }

    private Bitmap getColorMosaic() {
        if (mImageWidth <= 0 || mImageHeight <= 0) {
            return null;
        }

        Bitmap bitmap = Bitmap.createBitmap(mImageWidth, mImageHeight, Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Rect rect = new Rect(0, 0, mImageWidth, mImageHeight);
        Paint paint = new Paint();
        paint.setColor(mMosaicColor);
        canvas.drawRect(rect, paint);
        canvas.save();
        return bitmap;
    }

    private Bitmap getGridMosaic() {
        if (mImageWidth <= 0 || mImageHeight <= 0) {
            return null;
        }

        Bitmap bitmap = Bitmap.createBitmap(mImageWidth, mImageHeight, Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        int horCount = (int) Math.ceil(mImageWidth / (float) mGridWidth);
        int verCount = (int) Math.ceil(mImageHeight / (float) mGridWidth);

        Paint paint = new Paint();
        paint.setAntiAlias(true);

        for (int horIndex = 0; horIndex < horCount; ++horIndex) {
            for (int verIndex = 0; verIndex < verCount; ++verIndex) {
                int l = mGridWidth * horIndex;
                int t = mGridWidth * verIndex;
                int r = l + mGridWidth;
                if (r > mImageWidth) {
                    r = mImageWidth;
                }
                int b = t + mGridWidth;
                if (b > mImageHeight) {
                    b = mImageHeight;
                }
                int color = bmBaseLayer.getPixel(l, t);
                Rect rect = new Rect(l, t, r, b);
                paint.setColor(color);
                canvas.drawRect(rect, paint);
            }
        }
        canvas.save();
        return bitmap;
    }

    private Bitmap getBlurMosaic() {
        if (mImageWidth <= 0 || mImageHeight <= 0) {
            return null;
        }

        if (bmBaseLayer == null) {
            return null;
        }
        Bitmap bitmap = BitmapUtils.blur(bmBaseLayer);
        return bitmap;
    }

    public boolean isSaved() {
        return (bmCoverLayer == null);
    }

    public void setGridWidth(int width) {
        this.mGridWidth = dp2px(width);
    }

    public void setPathWidth(int width) {
        this.mPathWidth = dp2px(width);
    }

    public int getGridWidth() {
        return this.mGridWidth;
    }

    public void setStrokeColor(int color) {
        this.mStrokeColor = color;
        mPaint.setColor(mStrokeColor);
    }

    public void setMosaicColor(int color) {
        this.mMosaicColor = color;
    }

    public int getStrokeColor() {
        return this.mStrokeColor;
    }

    public void setStrokeWidth(int width) {
        this.mStrokeWidth = width;
        mPaint.setStrokeWidth(mStrokeWidth);
    }

    public int getStrokeWidth() {
        return this.mStrokeWidth;
    }

    public void setErase(boolean erase) {
        this.mMosaic = !erase;
    }

    public void setIsText(boolean isText) {
        this.isText = isText;
    }

    public void clear() {
        mTouchRects.clear();
        mEraseRects.clear();

        mTouchPaths.clear();
        mErasePaths.clear();

        isErase.clear();
        text = "";

        if (bmMosaicLayer != null) {
            bmMosaicLayer.recycle();
            bmMosaicLayer = null;
        }
        if (bmTextLayer != null) {
            bmTextLayer.recycle();
            bmTextLayer = null;
        }

        invalidate();
    }

    public boolean reset() {
        if (bmCoverLayer != null) {
            bmCoverLayer.recycle();
            bmCoverLayer = null;
        }
        if (bmBaseLayer != null) {
            bmBaseLayer.recycle();
            bmBaseLayer = null;
        }
        if (bmMosaicLayer != null) {
            bmMosaicLayer.recycle();
            bmMosaicLayer = null;
        }
        mTouchRects.clear();
        mEraseRects.clear();

        mTouchPaths.clear();
        mErasePaths.clear();
        return true;
    }

    public boolean dispatchTouchEvent(MotionEvent event) {
        super.dispatchTouchEvent(event);

        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        if (!isText) {
            onPathEvent(action, x, y);
        } else {
            if (action == MotionEvent.ACTION_MOVE) {
                textx = (int) event.getX();
                texty = (int) event.getY();
                getTextImage(text, textx, texty);
                invalidate();
            } else if (action == MotionEvent.ACTION_UP) {
                textx = (int) event.getX();
                texty = (int) event.getY();
                getTextImage(text, textx, texty);
                invalidate();
            }
        }
        return true;
    }

    private void onPathEvent(int action, int x, int y) {
        if (mImageWidth <= 0 || mImageHeight <= 0) {
            return;
        }

        if (x < mImageRect.left || x > mImageRect.right || y < mImageRect.top
                || y > mImageRect.bottom) {
            return;
        }

        float ratio = (mImageRect.right - mImageRect.left)
                / (float) mImageWidth;
        x = (int) ((x - mImageRect.left) / ratio);
        y = (int) ((y - mImageRect.top) / ratio);

        if (action == MotionEvent.ACTION_DOWN) {
            mTouchPath = new Path();
            mTouchPath.moveTo(x, y);
            if (mMosaic) {
                isErase.add(1);
                mTouchPaths.add(mTouchPath);
            } else {
                isErase.add(0);
                mErasePaths.add(mTouchPath);
            }
        } else if (action == MotionEvent.ACTION_MOVE) {
            try {
                mTouchPath.lineTo(x, y);
                updatePathMosaic();
                invalidate();
            } catch (Exception e) {
            }
        }
    }

    private void updatePathMosaic() {
        if (mImageWidth <= 0 || mImageHeight <= 0) {
            return;
        }
        if (bmMosaicLayer != null) {
            bmMosaicLayer.recycle();
        }
        bmMosaicLayer = Bitmap.createBitmap(mImageWidth, mImageHeight, Config.ARGB_8888);

        Bitmap bmTouchLayer = Bitmap.createBitmap(mImageWidth, mImageHeight, Config.ARGB_8888);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setPathEffect(new CornerPathEffect(10));
        paint.setStrokeWidth(mPathWidth);
        Canvas canvas = new Canvas(bmTouchLayer);

        int index_0 = 0;
        int index_1 = 0;
        for (Integer index : isErase) {
            if (index == 1) {
                paint.setColor(Color.BLUE);
                paint.setXfermode(null);
                canvas.drawPath(mTouchPaths.get(index_1), paint);
                index_1++;
            } else {
                paint.setColor(Color.TRANSPARENT);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                canvas.drawPath(mErasePaths.get(index_0), paint);
                index_0++;
            }
        }
        canvas.setBitmap(bmMosaicLayer);
        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawBitmap(bmCoverLayer, 0, 0, null);

        paint.reset();
        paint.setAntiAlias(true);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        canvas.drawBitmap(bmTouchLayer, 0, 0, paint);
        paint.setXfermode(null);
        canvas.save();

        bmTouchLayer.recycle();
    }

    @SuppressLint("DrawAllocation")
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (bmBaseLayer != null) {
            canvas.drawBitmap(bmBaseLayer, null, mImageRect, null);
        }
        if (bmMosaicLayer != null) {
            canvas.drawBitmap(bmMosaicLayer, null, mImageRect, null);
            canvas.drawBitmap(getTextImage(text, textx, texty), 0, 0, null);
            processOtherMsg(canvas);
        }
        if (mTouchRect != null) {
            canvas.drawRect(mTouchRect, mPaint);
        }
        if (text != null && !text.trim().equals("")) {

//	        canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.xingxing), 50, 50, null);
        }
    }

    /**
     * 处理文字,坐标,时间,logo信息
     *
     * @param canvas
     */
    @SuppressLint("SimpleDateFormat")
    private void processOtherMsg(Canvas canvas) {
        int width = (int) ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();//屏幕宽度
        int height = (int) ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight();//屏幕高度
        float rate = (float) width / 320;
        int textSize = (int) (12 * rate);
        TextPaint textPaint = new TextPaint();
        textPaint.setColor(Color.RED);  //设置画笔颜色      
        textPaint.setStrokeWidth(5);//设置画笔宽度  
        textPaint.setAntiAlias(true); //指定是否使用抗锯齿功能，如果使用，会使绘图速度变慢  
        textPaint.setTextSize(textSize);//设置文字大小  
        textPaint.setStyle(Paint.Style.FILL);  //绘图样式，设置为填充   
        //logo
        canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_ico), 40, 10, null);
        StaticLayout sl = null;
        //处理页面收到的文字
        if (text != null && !text.trim().equals("")) {
//	        sl= new StaticLayout(text,textPaint,width-60, Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
//	        canvas.translate(0, 60);
//	        sl.draw(canvas);     
        }
//        textPaint.setTextSize(40);//设置文字大小  

        if (ThisApp.aMapLocation != null) {
            //经度
            sl = new StaticLayout("      经度:" + ThisApp.aMapLocation.getLatitude() + "  纬度:" + ThisApp.aMapLocation.getLongitude(), textPaint, width - 60, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
            canvas.translate(0, height - (bottomHeight + 120));
            sl.draw(canvas);
            //地点
            sl = new StaticLayout("地点:" + ThisApp.aMapLocation.getCountry() + ThisApp.aMapLocation.getCity()  + ThisApp.aMapLocation.getPoiName(), textPaint, width - 60, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
            canvas.translate(0, textSize);
            sl.draw(canvas);
            //时间
            sl = new StaticLayout("      时间:" + DateTime.getStringDate(ThisApp.aMapLocation.getTime()), textPaint, width - 60, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
            canvas.translate(0, textSize);
            sl.draw(canvas);
        }
    }

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (mImageWidth <= 0 || mImageHeight <= 0) {
            return;
        }

        int contentWidth = right - left;
        int contentHeight = bottom - top;
        int viewWidth = contentWidth - mPadding * 2;
        int viewHeight = contentHeight - mPadding * 2;
        float widthRatio = viewWidth / ((float) mImageWidth);
        float heightRatio = viewHeight / ((float) mImageHeight);
        float ratio = widthRatio < heightRatio ? widthRatio : heightRatio;
        int realWidth = (int) (mImageWidth * ratio);
        int realHeight = (int) (mImageHeight * ratio);

        int imageLeft = (contentWidth - realWidth) / 2;
        int imageTop = (contentHeight - realHeight) / 2;
        int imageRight = imageLeft + realWidth;
        int imageBottom = imageTop + realHeight;
        mImageRect.set(imageLeft, imageTop, imageRight, imageBottom);
    }

    public int dp2px(int dip) {
        Context context = this.getContext();
        Resources resources = context.getResources();
        int px = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, resources.getDisplayMetrics()));
        return px;
    }

    /**
     * 返回值: Bitmap 参数：原图片,文字 功能: 根据给定的文字生成相应图片
     *
     * @param text 文字
     * @param x    点击的X坐标
     * @param y    点击的Y坐标
     * @return
     */
    public Bitmap getTextImage(String text, float x, float y) {
        if (bmTextLayer != null) {
            bmTextLayer.recycle();
            System.gc();
        }
//    	int h = mImageHeight;
        int w = mImageWidth;
        if (mImageWidth > mImageHeight) {
//        	h = mImageWidth;
            w = mImageHeight;
        }
        try {
            bmTextLayer = Bitmap.createBitmap(ScreenUtil.getScreenWidth(getContext()), ScreenUtil.getScreenHeight(getContext()) - 200, Config.ARGB_8888);
        } catch (Exception e) {
        }

        // 定义画布  
        Canvas canvas = new Canvas(bmTextLayer);
        float rate = (float) ScreenUtil.getScreenWidth(getContext()) / 320;
        int textSize = (int) (18 * rate);
        // 定义画笔  
        TextPaint textPaint = new TextPaint();
        textPaint.setColor(Color.RED);  //设置画笔颜色      
        textPaint.setStrokeWidth(5);//设置画笔宽度  
        textPaint.setAntiAlias(true); //指定是否使用抗锯齿功能，如果使用，会使绘图速度变慢  
        textPaint.setTextSize(textSize);//设置文字大小  
        textPaint.setStyle(Paint.Style.FILL);  //绘图样式，设置为填充   

        canvas.drawBitmap(bmTextLayer, 0, 0, null);
        StaticLayout sl = new StaticLayout(text, textPaint, w > 100 ? w - 100 : w, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
        canvas.translate(textx, texty);
        sl.draw(canvas);
        canvas.save();
        return bmTextLayer;
    }

    public void setBottomHeight(int height) {
        this.bottomHeight = height;
    }
}
